package main

import (
	"context"
	"flag"
	"fmt"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/tools/clientcmd"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"time"
)

type Server struct {
	Id     int
	Name   string
	Status string
}

//定义日志文件名
var (
	logFileName = flag.String("log", "cServer.log", "Log file name")
)
var warn []Server
var danger []Server
var send []Server

func main() {


	runtime.GOMAXPROCS(runtime.NumCPU())
	flag.Parse()
	//set logfile Stdout
	logFile, logErr := os.OpenFile(*logFileName, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0666)
	if logErr != nil {
		fmt.Println("Fail to find", *logFile, "cServer start Failed")
		os.Exit(1)
	}
	log.SetOutput(logFile)

	log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
	//write log

	//创建一个clientset
	cs := list()
	//第一次检查服务是否正常，异常时将服务放入warn切片,正常打印"无异常"
	listWarn(cs)
	//检查warn是否为空，不为空两分钟后，再次检查
	fmt.Println("test")
	if len(warn) != 0 {
		fmt.Println("test")
		time.Sleep(time.Second * 120)
		//第二次检查服务是否正常，异常时将服务放入danger切片
		listDanger(cs)
		//检查danger是否为空，不为空删除pod，两分钟后再次检查
		if len(danger) != 0 {
			for _,i := range danger{
				//删除pod
				delete(cs,i.Name)
			}
			time.Sleep(time.Second * 120)
			//第三次检查服务是否正常，异常时将服务放入send切片
			listsend(cs)
			if len(send) != 0{
				//遍历send，取出服务名和状态
				for _,server := range send {
					SendDingMsg("报警通知：" + server.Name + " 状态为：" + server.Status + "\n")
					log.Printf("报警通知：" + server.Name + " 状态为：" + server.Status + "\n")
				}
			}else {
				log.Printf("Server abort! Cause:%v \n", "出现异常，删除后正常")
			}
		}else {
			log.Printf("Server abort! Cause:%v \n", "可能正在发版")
		}
	}else {
		log.Printf("Server abort! Cause:%v \n", "无异常")
	}

}
func listDanger(cs *kubernetes.Clientset) {

	pods, err := cs.CoreV1().Pods("devops").List(context.TODO(), metav1.ListOptions{})
	if err != nil {
		panic(err.Error())
	}
	//列出所有处于非running状态的pod,加入到danger切片
	for i, pod := range pods.Items {
		if pod.Status.Phase != "Running" {
			status := Server{
				Id:     i,
				Name:   pod.Name,
				Status: string(pod.Status.Phase),
			}
			danger = append(danger, status)
		}
	}
}


func listWarn(cs *kubernetes.Clientset) {

	pods, err := cs.CoreV1().Pods("devops").List(context.TODO(), metav1.ListOptions{})
	if err != nil {
		panic(err.Error())
	}
	//列出所有处于非running状态的pod，加入到warn切片
	for i, pod := range pods.Items {
		if pod.Status.Phase != "Running" {
			status := Server{
				Id:     i,
				Name:   pod.Name,
				Status: string(pod.Status.Phase),
			}
			warn = append(warn, status)
			fmt.Println("状态不是running")
			fmt.Println(pod.Status.Phase)
			fmt.Println(pod.Name)
		}else {
			fmt.Println("状态时running")
			fmt.Println(pod.Status.Phase)
			fmt.Println(pod.Name)
		}
	}
}
func listsend(cs *kubernetes.Clientset) {

	pods, err := cs.CoreV1().Pods("devops").List(context.TODO(), metav1.ListOptions{})
	if err != nil {
		panic(err.Error())
	}
	//列出所有处于非running状态的pod，加入到send切片
	for i, pod := range pods.Items {
		if pod.Status.Phase != "Running" {
			status := Server{
				Id:     i,
				Name:   pod.Name,
				Status: string(pod.Status.Phase),
			}
			send = append(send, status)
		}
	}
}
func delete(cs *kubernetes.Clientset,name string) {

	err := cs.CoreV1().Pods("devops").Delete(context.TODO(), name, metav1.DeleteOptions{})
	if err != nil{
		panic(err.Error())
	}

}
func SendDingMsg(msg string) {
	//请求地址模板
	webHook := `https://oapi.dingtalk.com/robot/send?access_token=c6335176bada9f248ce723b9aaffba96a3dff35fae264dc10318e28d6e9173e5`
	content := `{"msgtype": "text",
		"text": {"content": "` + msg + `"}
	}`
	//创建一个请求
	req, err := http.NewRequest("POST", webHook, strings.NewReader(content))
	if err != nil {
		// handle error
	}

	client := &http.Client{}
	//设置请求头
	req.Header.Set("Content-Type", "application/json; charset=utf-8")
	//发送请求
	resp, err := client.Do(req)
	//关闭请求
	defer resp.Body.Close()

	if err != nil {
		// handle error
	}
}
func list() (cs *kubernetes.Clientset) {
	//列出所有pod
	var kubeconfig *string
	kubeconfig = flag.String("kubeconfig", filepath.Join("config"), "./config")
	flag.Parse()
	// use the current context in kubeconfig
	config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)
	if err != nil {
		panic(err.Error())
	}
	clientset, err := kubernetes.NewForConfig(config)
	if err != nil {
		panic(err.Error())
	}

	return clientset
}